package com.mxprojects.constructors
{
	import com.mxprojects.gui.Styles;
	import com.mxprojects.io.Config;
	import com.mxprojects.io.CustomEvent;
	
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.FocusEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	public class Dropdown extends MovieClip
	{
		public static const NULL_VALUE:String = "#NULL_VALUE#";
		public static const SELECT:String = "select";
		
		private const SPLITTER:String = "#SPLIT#";
		private const LABEL_X:int = 10;
		
		public var background:MovieClip;
		public var button:DropdownButton;
		public var list:DropdownList;
		
		private var selected:Sprite;
		//private var itemBackground:Sprite;
		private var itemHolder:Sprite;
		private var isOpen:Boolean = false;
		private var selectedY:int = 0;
		private var largestWidth:int = 0;
		private var labelText:SimpleTextField;
		private var openHeight:int;
		private var elements:Array = new Array();
		private var values:Array = new Array();
		private var defaultValue:String;
		private var currentValue:*;
		
		public function Dropdown(defaultValue:String = "") {						
			//set the common vars
			this.defaultValue = defaultValue;
			
			//setup the holders and put things in place
			setup();
			
			//make a default label in case we don't have a default value
//			if(defaultValue == ""){
//				defaultValue = Language.main(Word.SELECT) + "...";
//			}
			labelText = new SimpleTextField("<span class=\"dropdownElement\">" + defaultValue + "</span>");
			labelText.x = LABEL_X;
			labelText.mouseEnabled = false;
			addChild(labelText);
			
			//make the current selection null
			value = NULL_VALUE;
			
			//set the largest width in the event THIS is the largest
			largestWidth = labelText.width;
			
			//make the down area and default area listen to mouse clicks
			background.addEventListener(MouseEvent.CLICK, toggle, false, 0, true);
			button.addEventListener(MouseEvent.CLICK, toggle, false, 0, true);
			addEventListener(MouseEvent.CLICK, focusMenu, false, 0, true);
			
			//make sure the displayed text is center
			labelText.y = Math.round(background.height/2 - labelText.height/2) - 1; 
		}
		
		public function set label(text:String):void {
			labelText.htmlText = "<span class=\"dropdownElement\">" + text + "</span>";
		}
		
		public function get label():String {
			return labelText.text;
		}
		
		public function set value(value:*):void {
			currentValue = value;
		}
		
		public function get value():* {
			return currentValue;
		}
		
		override public function get height():Number {
			//return the proper height
			return background.height;
		}
		
		override public function set width(value:Number):void {
			background.width = value - button.width;
			button.x = background.width;
			list.width = value;
			selected.width = value;
			adjustHighlights();
		}
		
		override public function set enabled(isEnabled:Boolean):void {
			//this will handle the state of things when enabled is disabled
			if(isEnabled){
				alpha = 1;
				background.addEventListener(MouseEvent.CLICK, toggle, false, 0, true);
				button.addEventListener(MouseEvent.CLICK, toggle, false, 0, true);
			}else{
				alpha = Config.BUTTON_DISABLED_ALPHA;
				background.removeEventListener(MouseEvent.CLICK, toggle);
				button.removeEventListener(MouseEvent.CLICK, toggle);
			}
			
			//handle the mouse
			mouseEnabled = isEnabled;
			mouseChildren = isEnabled;
		}
		
		public function addItem(name:String, value:*, instantUpdate:Boolean):void {
			//shove them into the arrays
			elements.push(name);
			values.push(value);
			
			if(instantUpdate){
				update();
			}
		}
		
		public function addItemAt(name:String, value:*, placement:int):void {
			//this will insert an item at a certain place and auto-update the dropdown
			elements.splice(placement, 0, name);
			values.splice(placement, 0, value);
			
			update();
		}
		
		public function removeAll():void {
			//just removes all the stuff
			elements = new Array();
			values = new Array();
			largestWidth = 0;
			
			update();
		}
		
		public function update():void {
			//simple function that updates the dropdown if you've added anything to it
			//create the elements
			createElements();
		}
		
		private function setup():void {
			//the default background
			Styles.setProperties(background, ".dropdownBackground");
			
			//the dropdown button
			Styles.setProperties(button.background, ".dropdownButtonBackground");
			Styles.setProperties(button.arrow, ".dropdownButtonArrow");			
		}
		
		private function createElements():void {
			//create a new holder
			if(itemHolder != null){
				removeChild(itemHolder);
			}
			itemHolder = new Sprite();
			
			//create the selector
			selected = new Sprite();
			
			//disable the mouse on the selector
			selected.mouseEnabled = false;
			
			//add it to the item holder (at the bottom) each node will push it up
			itemHolder.addChildAt(selected, 0); 
			
			//loop through the elements to create the text boxes
			var nextY:int = 0;
			
			//set a default button highlight incase the dropdown doesn't have anything yet
			var buttonHighlight:ButtonHighlight = null;
			
			for(var i:int = 0; i < elements.length; i++){
				//if it's the first element and there is no default value, set it as the default value
				if(i == 0 && defaultValue == ""){
					label = elements[i];
				}
				
				
				//make a text box and attach it to the background
				var textBox:SimpleTextField = new SimpleTextField("<span class=\"dropdownElement\">" + elements[i] + "</span>");
				if(values[i] == NULL_VALUE){
					textBox.htmlText = "<span class=\"dropdownUnselectable\">" + elements[i] + "</span>";
				}
				textBox.x = Math.round(Config.TEXT_PADDING);
				textBox.y = nextY;
				textBox.mouseEnabled = false;
				nextY += textBox.height;
				
				//see if it's the largest element
				if(textBox.width > largestWidth){
					largestWidth = textBox.width;
				}
				
				//create a mouseover box thing
				if(values[i] != NULL_VALUE){
					buttonHighlight = new ButtonHighlight(textBox, select, false);
					buttonHighlight.width = textBox.width + Config.TEXT_PADDING;
					buttonHighlight.height = textBox.height;
					buttonHighlight.y = textBox.y;
					buttonHighlight.alpha = 0;
					
					//give the highlight a name that relates to the value so we can call it when it's clicked
					buttonHighlight.name = elements[i] + SPLITTER + values[i];
					
					//at the child at the bottom so that it pushes the selector up
					itemHolder.addChildAt(buttonHighlight, 0);
					
					//this will snap the selected box to the current location
					buttonHighlight.addEventListener(MouseEvent.ROLL_OVER, snapSelection, false, 0, true);
				}
				
				//if this one is the same as the selected, make sure to move the selected box
				if(defaultValue != "" && values[i] == defaultValue){
					//move the selected box up here
					selected.y = buttonHighlight.y;
					
					//set the shared var
					selectedY = selected.y;
					
					//populate the default text
					label = elements[i];
					value = values[i];
				}
				
				if(selectedY == 0 && values[0] == NULL_VALUE){
					//push the selector down a peg
					//make sure you get the next non-null value
					var valuesLength:int = values.length;
					var currentElement:int = 0;
					
					while(currentElement < valuesLength){
						if(values[currentElement] == NULL_VALUE){
							selectedY += textBox.height;
						}else{
							//we hit a good one, break out
							break;
						}
						currentElement++;
					}
				}
				
				//add it to the background
				itemHolder.addChild(textBox);
			}
			
			//set the open height
			openHeight = Math.round(itemHolder.height);
			
			//position the background and button so it can fit the largest element
			background.width = Math.ceil(largestWidth + Config.TEXT_PADDING);
			if(Math.ceil(labelText.height) > background.height){
				//if our text is large, then make the height fit the text
				background.height = Math.ceil(labelText.height);
			}else{
				//otherwise center the text
				labelText.y = Math.round(background.height/2 - labelText.height/2) - 1;
			}
			button.height = background.height;
			button.width = button.height;
			button.x = background.width;
			
			//set up the item background
			list.setup(background.width + button.width, openHeight);
			Styles.setProperties(list, ".dropdownItemBackground");
			
			//setup the items
			addChild(itemHolder);
						
			//after we've got everything make all the boxes the right size
			adjustHighlights();
			
			//hide the selected and set it to the width
			var buttonWidth:int = 1;
			var buttonHeight:int = 1;
			
			if(buttonHighlight != null){
				buttonWidth = buttonHighlight.width;
				buttonHeight = buttonHighlight.height;
			}
			
			//draw the selector
			selected.graphics.beginFill(0x999999);
			selected.graphics.drawRect(0, 0, buttonWidth, buttonHeight);
			selected.graphics.endFill();
			Styles.setProperties(selected, ".dropdownSelected");
						
			//close it up
			close();
		}
		
		private function toggle(event:MouseEvent):void {
			//open or close this thang
			if(isOpen){
				close();
			}else{
				open();
			}
		}
		
		private function open():void {
			isOpen = true;
			list.visible = true;
			list.height = openHeight;
			
			//flip the arrow
			button.flipArrow(isOpen);
			
			//if the thing is going to go past the stage, then flip it up
			var point:Point = button.localToGlobal(new Point(button.x, button.y));
			if(point.y + openHeight + button.height > stage.stageHeight){
				//flip it upwards
				list.y = -openHeight;
			}else{
				//put it below
				list.y = button.height;
			}
			
			//offset it by the top part of the list
			list.y -= Math.round(list.listTop.height);
			
			itemHolder.height = openHeight;
			itemHolder.y = Math.round(list.y + list.listTop.height);
			itemHolder.visible = true;
						
			//put the selector where it should be
			selected.y = selectedY;
			
			//add a listener to see if this ever loses focus
			focusRect = false;
			stage.focus = this;
			stage.addEventListener(FocusEvent.FOCUS_OUT, checkClick, false, 0, true);
			
			//force it to the top of the display list
			parent.setChildIndex(this, parent.numChildren - 1);
		}
		
		private function close(event:FocusEvent = null):void {
			isOpen = false;
			
			//flip the arrow
			button.flipArrow(isOpen);
						
			list.y = 0;
			list.height = background.height;
			list.visible = false;
			
			itemHolder.y = list.y;
			itemHolder.height = list.height;
			itemHolder.visible = false;
		}
		
		private function select(event:MouseEvent):void {
			//make sure we close the menu before making a selection
			close();
			
			//split up the name so we have name/value
			var chunks:Array = String(event.currentTarget.name).split(SPLITTER);
			
			//set the label and value
			label = chunks[0];
			value = chunks[1];
			
			//fire the event
			dispatchEvent(new CustomEvent(SELECT, chunks[0], chunks[1]));
		}
		
		private function checkClick(event:FocusEvent):void {			
			//where did they click in order to lose focus?
			if(stage != null){
				if(!hitTestPoint(stage.mouseX, stage.mouseY)){
					//if we didn't hit the dropdown then just close it
					stage.removeEventListener(FocusEvent.FOCUS_OUT, checkClick);
					close();
				}
			}
		}
		
		private function focusMenu(event:MouseEvent):void {
			//this will just focus the dropdown
			if(stage != null){
				stage.focus = this;
			}
		}
		
		private function snapSelection(event:MouseEvent):void {
			//this will move the selection MC to the right spot
			var buttonHighlight:ButtonHighlight = event.currentTarget as ButtonHighlight;
			selected.y = buttonHighlight.y;
		}
		
		private function adjustHighlights():void {
			//just loop through the children and if we have a highlight, increase the width
			var buttonHighlight:ButtonHighlight;
			
			for(var i:int = 0; i < itemHolder.numChildren; i++){
				if(itemHolder.getChildAt(i) is ButtonHighlight){
					//set it's width
					buttonHighlight = itemHolder.getChildAt(i) as ButtonHighlight;
					buttonHighlight.width = list.width;
				}
			}
		}

	}
}